package service

import (
	"errors"
	"fmt"
	"mime/multipart"
	"path/filepath"
	"strings"
	"time"
	"wms/internal/model"
	"wms/internal/model/request"
	"wms/internal/model/response"
	"wms/pkg/database"
	"wms/pkg/logger"
	"wms/pkg/utils"

	"go.uber.org/zap"
	"gorm.io/gorm"
)

// UserService 用户服务
type UserService struct {
	db *gorm.DB
}

// NewUserService 创建用户服务
func NewUserService() *UserService {
	return &UserService{
		db: database.GetDB(),
	}
}

// Login 用户登录
func (s *UserService) Login(req *request.LoginRequest) (*response.LoginResponse, error) {
	var user model.User

	// 查询用户
	if err := s.db.Where("username = ?", req.Username).First(&user).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			// 记录登录失败日志
			logger.LogLogin(req.Username, 0, false, req.IP)
			return nil, errors.New("用户名或密码错误")
		}
		return nil, err
	}

	// 验证密码
	if !user.CheckPassword(req.Password) {
		// 记录登录失败日志
		logger.LogLogin(req.Username, user.ID, false, req.IP)
		return nil, errors.New("用户名或密码错误")
	}

	// 验证用户状态
	if user.Status != 1 {
		// 记录登录失败日志
		logger.LogLogin(req.Username, user.ID, false, req.IP)
		return nil, errors.New("用户已禁用")
	}

	// 获取角色名称
	roleName, err := s.GetRoleNameByID(user.RoleID)
	if err != nil {
		logger.Error("获取角色名称失败", zap.Error(err))
		roleName = "未知角色"
	}

	// 生成Token
	token, err := utils.GenerateToken(user.ID, user.Username, user.RoleID)
	if err != nil {
		return nil, err
	}

	// 更新最后登录时间
	if err := s.db.Model(&user).Update("last_login", time.Now()).Error; err != nil {
		logger.Error("更新最后登录时间失败", zap.Error(err))
	}

	// 记录登录成功日志
	logger.LogLogin(user.Username, user.ID, true, req.IP)

	// 返回登录响应
	return &response.LoginResponse{
		Token:    token,
		UserID:   user.ID,
		Username: user.Username,
		Nickname: user.Nickname,
		Avatar:   user.Avatar,
		RoleID:   user.RoleID,
		RoleName: roleName,
	}, nil
}

// GetUsers 获取用户列表
func (s *UserService) GetUsers(req *request.UserListRequest) ([]model.User, int64, error) {
	var users []model.User
	var total int64

	query := s.db.Model(&model.User{})

	// 搜索关键词
	if req.Keyword != "" {
		query = query.Where("username LIKE ? OR nickname LIKE ? OR email LIKE ? OR phone LIKE ?",
			"%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%", "%"+req.Keyword+"%")
	}

	// 状态筛选
	if req.Status != nil {
		query = query.Where("status = ?", *req.Status)
	}

	// 获取总数
	if err := query.Count(&total).Error; err != nil {
		logger.Error("获取用户总数失败", zap.Error(err))
		return nil, 0, err
	}

	// 分页查询，添加预加载Role关系
	offset := (req.Page - 1) * req.PageSize
	if err := query.Preload("Role").Offset(offset).Limit(req.PageSize).Find(&users).Error; err != nil {
		logger.Error("获取用户列表失败", zap.Error(err))
		return nil, 0, err
	}

	return users, total, nil
}

// GetUserByID 根据ID获取用户
func (s *UserService) GetUserByID(id uint) (*model.User, error) {
	var user model.User
	if err := s.db.Where("id = ?", id).First(&user).Error; err != nil {
		// 如果是记录未找到错误，可以返回更具体的错误或nil, nil
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户不存在")
		}
		return nil, err
	}
	return &user, nil
}

// GetRoleNameByID 根据角色ID获取角色名称
func (s *UserService) GetRoleNameByID(roleID uint) (string, error) {
	var role model.Role
	if err := s.db.Where("id = ?", roleID).Select("name").First(&role).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return "", errors.New("角色不存在") // Or return a default/empty string
		}
		return "", err
	}
	return role.Name, nil
}

// CreateUser 创建用户
func (s *UserService) CreateUser(req *request.UserCreateRequest) error {
	hashedPassword := (&model.User{}).HashPassword(req.Password)
	user := &model.User{
		Username: req.Username,
		Password: hashedPassword,
		Nickname: req.Nickname,
		Email:    req.Email,
		Phone:    req.Phone,
		RoleID:   req.RoleID,
		Status:   req.Status,
	}

	if err := s.db.Create(user).Error; err != nil {
		logger.Error("创建用户失败", zap.Error(err))
		return err
	}

	return nil
}

// UpdateUser 更新用户
func (s *UserService) UpdateUser(req *request.UserUpdateRequest) error {
	user := &model.User{
		ID:       req.ID,
		Nickname: req.Nickname,
		Email:    req.Email,
		Phone:    req.Phone,
		RoleID:   req.RoleID,
		Status:   req.Status,
	}

	if err := s.db.Model(&model.User{}).Where("id = ?", req.ID).Updates(user).Error; err != nil {
		logger.Error("更新用户失败", zap.Error(err))
		return err
	}

	return nil
}

// DeleteUser 删除用户
func (s *UserService) DeleteUser(id uint) error {
	if err := s.db.Delete(&model.User{}, id).Error; err != nil {
		logger.Error("删除用户失败", zap.Error(err))
		return err
	}
	return nil
}

// SetUserStatus 设置用户状态
func (s *UserService) SetUserStatus(req *request.UserStatusRequest) error {
	if err := s.db.Model(&model.User{}).Where("id = ?", req.ID).Update("status", req.Status).Error; err != nil {
		logger.Error("设置用户状态失败", zap.Error(err))
		return err
	}
	return nil
}

// UpdatePassword 修改密码
func (s *UserService) UpdatePassword(req *request.PasswordUpdateRequest, userID uint) error {
	// 通过userID查询具体用户
	var user model.User
	if err := s.db.First(&user, userID).Error; err != nil {
		logger.Error("查询用户失败", zap.Error(err), zap.Uint("userID", userID))
		return err
	}

	// 验证旧密码
	if !user.CheckPassword(req.OldPassword) {
		return errors.New("旧密码错误")
	}

	// 直接设置密码，让模型的钩子函数处理哈希
	user.Password = req.NewPassword

	// 使用Save触发BeforeUpdate钩子
	if err := s.db.Save(&user).Error; err != nil {
		logger.Error("更新密码失败", zap.Error(err))
		return err
	}

	return nil
}

// UpdateProfile 更新个人信息
func (s *UserService) UpdateProfile(userID uint, req *request.ProfileUpdateRequest) error {
	updates := map[string]interface{}{
		"nickname": req.Nickname,
		"email":    req.Email,
		"phone":    req.Phone,
	}

	if err := s.db.Model(&model.User{}).Where("id = ?", userID).Updates(updates).Error; err != nil {
		logger.Error("更新个人信息失败", zap.Error(err))
		return err
	}

	return nil
}

// UploadAvatar 上传头像
func (s *UserService) UploadAvatar(userID uint, file *multipart.FileHeader) (string, error) {
	// 首先获取用户信息，以便获取用户名
	var user model.User
	if err := s.db.First(&user, userID).Error; err != nil {
		return "", fmt.Errorf("找不到用户: %w", err)
	}

	// 使用用户名创建目录
	userName := user.Username
	if userName == "" {
		return "", fmt.Errorf("用户名为空")
	}

	// 获取文件扩展名
	ext := filepath.Ext(file.Filename)
	if ext == "" {
		ext = ".jpg" // 默认扩展名
	}

	// 确保扩展名为小写
	ext = strings.ToLower(ext)

	// 设置固定的文件名为avatar.jpg或保留原始扩展名
	fileName := "avatar" + ext

	// 创建用户专属目录
	userDir := filepath.Join("static", "uploads", "users", userName)

	// 保存文件路径
	dst := filepath.Join(userDir, fileName)

	// 保存文件
	if err := utils.SaveUploadedFile(file, dst); err != nil {
		return "", fmt.Errorf("保存文件失败: %w", err)
	}

	// 添加时间戳查询参数以防止缓存
	timestamp := time.Now().Unix()

	// 更新用户头像URL
	avatarURL := fmt.Sprintf("/static/uploads/users/%s/%s?t=%d", userName, fileName, timestamp)

	if err := s.db.Model(&model.User{}).Where("id = ?", userID).Update("avatar", avatarURL).Error; err != nil {
		return "", fmt.Errorf("更新用户头像记录失败: %w", err)
	}

	return avatarURL, nil
}

// GetRoleByID 根据ID获取角色
func (s *UserService) GetRoleByID(id uint) (*model.Role, error) {
	var role model.Role
	if err := s.db.First(&role, id).Error; err != nil {
		return nil, err
	}
	return &role, nil
}
